(*
 * This software is distributed under BSD license.
 *
 * Copyright (c) 2009-2014 Iztok Kacin, Cromis (iztok.kacin@gmail.com).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 * - Neither the name of the Iztok Kacin nor the names of its contributors may be
 *   used to endorse or promote products derived from this software without specific
 *   prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * =============================================================================
 * Common thread safe classes code for both TAnyValue and Generics implementation
 * Refer to Cromis.Threading for changelog
 * =============================================================================
*)
unit Cromis.Threading.TS.Common;

interface

uses
  Windows, SysUtils;

const
  cDefaultSize = 5000;

{$IFNDEF Threading_NoLockFreeStack}
var
  CallInitializeSListHead: procedure(ListHead: Pointer); stdcall;
  CallInterlockedPopEntrySList: function(ListHead: Pointer): Pointer; stdcall;
  CallInterlockedPushEntrySList: function(ListHead: Pointer; ListEntry: Pointer): Pointer; stdcall;
  CallInterlockedFlushSList: function(ListHead: Pointer): Pointer; stdcall;
  CallQueryDepthSList: function(ListHead: Pointer): Word; stdcall;
{$ENDIF}

implementation

var
  KernelHandle: HModule;

initialization
  KernelHandle := GetModuleHandle(kernel32);

{$IFNDEF Threading_NoLockFreeStack}
  @CallInitializeSListHead := GetProcAddress(KernelHandle, 'InitializeSListHead');
  @CallInterlockedPopEntrySList := GetProcAddress(KernelHandle, 'InterlockedPopEntrySList');
  @CallInterlockedPushEntrySList := GetProcAddress(KernelHandle, 'InterlockedPushEntrySList');
  @CallInterlockedFlushSList := GetProcAddress(KernelHandle, 'InterlockedFlushSList');
  @CallQueryDepthSList := GetProcAddress(KernelHandle, 'QueryDepthSList');

  if (not Assigned(CallInitializeSListHead)) or
     (not Assigned(CallInterlockedPopEntrySList)) or
     (not Assigned(CallInterlockedPushEntrySList)) or
     (not Assigned(CallInterlockedFlushSList)) or
     (not Assigned(CallQueryDepthSList)) then
    raise Exception.Create('LockFree Stack API functions are not supported!');
{$ENDIF}

finalization
  FreeLibrary(KernelHandle);

end.
